home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / gr564s.zip / SRC / RCSCLEAN.C < prev    next >
C/C++ Source or Header  |  1992-09-05  |  7KB  |  319 lines

  1. /* rcsclean - clean up working files */
  2.  
  3. /* Copyright 1991, 1992 by Paul Eggert
  4.    Distributed under license by the Free Software Foundation, Inc.
  5.  
  6. This file is part of RCS.
  7.  
  8. RCS is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2, or (at your option)
  11. any later version.
  12.  
  13. RCS is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with RCS; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. Report problems and direct all questions to:
  23.  
  24.     rcs-bugs@cs.purdue.edu
  25.  
  26. */
  27.  
  28. #include "rcsbase.h"
  29.  
  30. #if has_dirent
  31.     static int get_directory P((char const*,char***));
  32. #endif
  33.  
  34. static int unlock P((struct hshentry *));
  35. static void cleanup P((void));
  36.  
  37. static RILE *workptr;
  38. static int exitstatus;
  39.  
  40. mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.4 1992/07/28 16:12:44 eggert Exp $")
  41. {
  42.     static char const usage[] =
  43.         "\nrcsclean: usage: rcsclean [-ksubst] [-{nqru}[rev]] [-Vn] [-xsuffixes] [file ...]";
  44.  
  45.     static struct buf revision;
  46.  
  47.     char *a, **newargv;
  48.     char const *rev, *p;
  49.     int argc_min;
  50.     int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
  51.     int Ttimeflag;
  52.     struct hshentries *deltas;
  53.     struct hshentry *delta;
  54.     struct stat workstat;
  55.  
  56.     setrid();
  57.  
  58.     argc_min = 1;
  59.     expmode = -1;
  60.     rev = nil;
  61.     suffixes = X_DEFAULT;
  62.     perform = true;
  63.     unlockflag = false;
  64.     Ttimeflag = false;
  65.  
  66.     argc = getRCSINIT(argc, argv, &newargv);
  67.     argv = newargv;
  68.     for (;;) {
  69.         if (--argc < argc_min) {
  70. #            if has_dirent
  71.                 argc = get_directory(".", &newargv);
  72.                 argv = newargv;
  73.                 break;
  74. #            else
  75.                 faterror("no pathnames specified");
  76. #            endif
  77.         }
  78.         a = *++argv;
  79.         if (!*a  ||  *a++ != '-')
  80.             break;
  81.         switch (*a++) {
  82.             case 'k':
  83.                 if (0 <= expmode)
  84.                     redefined('k');
  85.                 if ((expmode = str2expmode(a))  <  0)
  86.                     goto unknown;
  87.                 break;
  88.  
  89.             case 'n':
  90.                 perform = false;
  91.                 goto handle_revision;
  92.  
  93.             case 'q':
  94.                 quietflag = true;
  95.                 /* fall into */
  96.             case 'r':
  97.             handle_revision:
  98.                 if (*a) {
  99.                     if (rev)
  100.                         warn("redefinition of revision number");
  101.                     rev = a;
  102.                 }
  103.                 break;
  104.  
  105.             case 'T':
  106.                 if (*a)
  107.                     goto unknown;
  108.                 Ttimeflag = true;
  109.                 break;
  110.  
  111.             case 'u':
  112.                 unlockflag = true;
  113.                 goto handle_revision;
  114.  
  115.             case 'V':
  116.                 argc_min = setRCSversion(*argv);
  117.                 break;
  118.  
  119.             case 'x':
  120.                 suffixes = a;
  121.                 break;
  122.  
  123.             default:
  124.             unknown:
  125.                 faterror("unknown option: %s%s", *argv, usage);
  126.         }
  127.     }
  128.  
  129.     dounlock = perform & unlockflag;
  130.  
  131.     for (;  0 < argc;  cleanup(), ++argv, --argc) {
  132.         ffree();
  133.  
  134.         if (!(
  135.             0 < pairnames(
  136.                 argc, argv,
  137.                 dounlock ? rcswriteopen : rcsreadopen,
  138.                 true, true
  139.             ) &&
  140.             (workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
  141.         ))
  142.             continue;
  143.  
  144.         if (same_file(RCSstat, workstat, 0)) {
  145.             error("RCS file %s and working file %s are the same",
  146.                 RCSname, workname
  147.             );
  148.             continue;
  149.         }
  150.  
  151.         gettree();
  152.  
  153.         p = 0;
  154.         if (rev) {
  155.             if (!fexpandsym(rev, &revision, workptr))
  156.                 continue;
  157.             p = revision.string;
  158.         } else if (Head)
  159.             switch (unlockflag ? findlock(false,&delta) : 0) {
  160.                 default:
  161.                     continue;
  162.                 case 0:
  163.                     p = Dbranch ? Dbranch : "";
  164.                     break;
  165.                 case 1:
  166.                     p = delta->num;
  167.                     break;
  168.             }
  169.         delta = 0;
  170.         deltas = 0;  /* Keep lint happy.  */
  171.         if (p  &&  !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
  172.             continue;
  173.  
  174.         waslocked = delta && delta->lockedby;
  175.         locker_expansion = unlock(delta);
  176.         unlocked = locker_expansion & unlockflag;
  177.         if (unlocked<waslocked  &&  workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
  178.             continue;
  179.  
  180.         if (unlocked && !checkaccesslist())
  181.             continue;
  182.  
  183.         if (dorewrite(dounlock, unlocked) != 0)
  184.             continue;
  185.  
  186.         if (0 <= expmode)
  187.             Expand = expmode;
  188.         else if (
  189.             waslocked  &&
  190.             Expand == KEYVAL_EXPAND  &&
  191.             WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
  192.         )
  193.             Expand = KEYVALLOCK_EXPAND;
  194.  
  195.         getdesc(false);
  196.  
  197.         if (
  198.             !delta ? workstat.st_size!=0 :
  199.             0 < rcsfcmp(
  200.                 workptr, &workstat,
  201.                 buildrevision(deltas, delta, (FILE*)0, false),
  202.                 delta
  203.             )
  204.         )
  205.             continue;
  206.  
  207.         if (quietflag < unlocked)
  208.             aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
  209.  
  210.         if (perform & unlocked) {
  211.             if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
  212.             if (donerewrite(true, Ttimeflag) != 0)
  213.                 continue;
  214.         }
  215.  
  216.         if (!quietflag)
  217.             aprintf(stdout, "rm -f %s\n", workname);
  218.         Izclose(&workptr);
  219.         if (perform  &&  un_link(workname) != 0)
  220.             eerror(workname);
  221.  
  222.     }
  223.  
  224.     tempunlink();
  225.     if (!quietflag)
  226.         Ofclose(stdout);
  227.     exitmain(exitstatus);
  228. }
  229.  
  230.     static void
  231. cleanup()
  232. {
  233.     if (nerror) exitstatus = EXIT_FAILURE;
  234.     Izclose(&finptr);
  235.     Izclose(&workptr);
  236.     Ozclose(&fcopy);
  237.     ORCSclose();
  238.     dirtempunlink();
  239. }
  240.  
  241. #if RCS_lint
  242. #       define exiterr rcscleanExit
  243. #endif
  244.     exiting void
  245. exiterr()
  246. {
  247.     dirtempunlink();
  248.     tempunlink();
  249.     _exit(EXIT_FAILURE);
  250. }
  251.  
  252.     static int
  253. unlock(delta)
  254.     struct hshentry *delta;
  255. {
  256.     register struct lock **al, *l;
  257.  
  258.     if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
  259.         for (al = &Locks;  (l = *al);  al = &l->nextlock)
  260.             if (l->delta == delta) {
  261.                 *al = l->nextlock;
  262.                 delta->lockedby = 0;
  263.                 return true;
  264.             }
  265.     return false;
  266. }
  267.  
  268. #if has_dirent
  269.     static int
  270. get_directory(dirname, aargv)
  271.     char const *dirname;
  272.     char ***aargv;
  273. /*
  274.  * Put a vector of all DIRNAME's directory entries names into *AARGV.
  275.  * Ignore names of RCS files.
  276.  * Yield the number of entries found.  Terminate the vector with 0.
  277.  * Allocate the storage for the vector and entry names.
  278.  * Do not sort the names.  Do not include '.' and '..'.
  279.  */
  280. {
  281.     int i, entries = 0, entries_max = 64;
  282.     size_t chars = 0, chars_max = 1024;
  283.     size_t *offset = tnalloc(size_t, entries_max);
  284.     char *a = tnalloc(char, chars_max), **p;
  285.     DIR *d;
  286.     struct dirent *e;
  287.  
  288.     if (!(d = opendir(dirname)))
  289.         efaterror(dirname);
  290.     while ((errno = 0,  e = readdir(d))) {
  291.         char const *en = e->d_name;
  292.         size_t s = strlen(en) + 1;
  293.         if (en[0]=='.'   &&   (!en[1]  ||  en[1]=='.' && !en[2]))
  294.             continue;
  295.         if (rcssuffix(en))
  296.             continue;
  297.         while (chars_max < s + chars)
  298.             a = trealloc(char, a, chars_max<<=1);
  299.         if (entries == entries_max)
  300.             offset = trealloc(size_t, offset, entries_max<<=1);
  301.         offset[entries++] = chars;
  302.         VOID strcpy(a+chars, en);
  303.         chars += s;
  304.     }
  305.     if (errno  ||  closedir(d) != 0)
  306.         efaterror(dirname);
  307.     if (chars)
  308.         a = trealloc(char, a, chars);
  309.     else
  310.         tfree(a);
  311.     *aargv = p = tnalloc(char*, entries+1);
  312.     for (i=0; i<entries; i++)
  313.         *p++ = a + offset[i];
  314.     *p = 0;
  315.     tfree(offset);
  316.     return entries;
  317. }
  318. #endif
  319.